// Copyright (c) 2011 Blue Onion Software, All rights reserved
using System;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace BlueOnionSoftware.Bloget
{
    /// <summary>
    /// Displays a push button control on the Web page.
    /// When the user clicks the button, a dialog box appears asking to confirm the action.
    /// </summary>
    /// <remarks>
    /// Use the ConfirmedButton to create a button on the page which makes sure the user really wanted to push it.
    /// This is a common requirement of buttons which delete or change data.
    /// After clicking the button, but before the page maxPosts back to the server, the user is asked to confirm the action.
    /// The text of the message displayed is set with the <see cref="ConfirmedButton.Message"/> property.
    /// </remarks>
    /// <example>
    /// The following example demonstrates how to create a submit Button which confirms an important action.
    /// <code>
    /// <![CDATA[
    /// <%@ Page Language="C#" %>
    /// <%@ Register tagprefix="mbcb" namespace="MetaBuilders.WebControls" assembly="MetaBuilders.WebControls.ConfirmedButtons" %>
    /// <script runat="server">
    ///     protected void MyButton_Click( Object Sender, EventArgs E ) {
    ///         Result.Text = System.DateTime.Now.ToString();
    ///     }
    /// </script>
    /// <html>
    /// 	<contentML>
    /// 	<form runat="server">
    ///         <mbcb:ConfirmedButton runat="server" id="MyButton" Text="Click Me" Message="Are you sure?" onclick="MyButton_Click" />
    ///         <asp:Label runat="server" id="Result" />
    /// 	</form>
    /// 	</contentML>
    /// </html>
    /// ]]>
    /// </code>
    /// </example>
    public class ConfirmedButton : Button
    {
        /// <summary>
        /// Gets or sets the message displayed to confirm the action before postback.
        /// </summary>
        /// <xmlRpcValue>The message displayed to confirm the action before postback. The default xmlRpcValue is "Are you sure you want to do this?".</xmlRpcValue>
        [
            Description("Gets or sets the message displayed to confirm the action before postback."),
            DefaultValue("Are you sure you want to do this?"),
            Category("Behavior"),
            Bindable(true)
        ]
        public String Message
        {
            get
            {
                object savedState;

                savedState = ViewState["Message"];
                if (savedState != null)
                {
                    return (String) savedState;
                }
                return "Are you sure you want to do this?";
            }
            set { ViewState["Message"] = value; }
        }

        /// <summary>
        /// Gets or sets if the message set with <see cref="Message"/> will be displayed.
        /// </summary>
        /// <remarks>There are times when the developer only wants the user to view the message the first time.
        /// This can be done by setting MessageEnabled to false in the click event handler for the button.
        /// </remarks>
        [
            Description("Gets or sets if the message set with Message will be displayed."),
            DefaultValue(true),
            Category("Behavior"),
            Bindable(true)
        ]
        public Boolean MessageEnabled
        {
            get
            {
                object savedState;

                savedState = ViewState["MessageEnabled"];

                if (savedState != null)
                {
                    return (Boolean) savedState;
                }
                return true;
            }
            set { ViewState["MessageEnabled"] = value; }
        }

        /// <summary>
        /// Adds to the specified writer those HTML attributes and styles that need to be rendered. This method is primarily used by control developers.
        /// </summary>
        /// <param name="writer">The output stream that renders HTML text to the client.</param>
        /// <remarks>
        /// Overridden to add the <see cref="ConfirmedButton.Message"/> to the Attributes collection.
        /// </remarks>
        protected override void AddAttributesToRender(HtmlTextWriter writer)
        {
            base.AddAttributesToRender(writer);
            if (MessageEnabled)
            {
                if (ClientScriptUtility.RenderUpLevel)
                {
                    writer.AddAttribute("confirmationmessage", Message);
                }

                else
                {
                    writer.AddAttribute("onclick",
                                        "javascript: return confirm( &quot;" + Message.Replace("\"", "&quot;") +
                                            "&quot; )", false);
                }
            }
        }

        /// <summary>
        /// Raises the PreRender event, which notifies the server control that is about to be rendered to the page.
        /// </summary>
        /// <remarks>Overridden to register client script with the <see cref="Page"/></remarks>
        /// <param name="e">An <see cref="EventArgs"/> object that contains the event data. </param>
        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);

            if (MessageEnabled)
            {
                if (ClientScriptUtility.RenderUpLevel)
                {
                    RegisterClientScript();
                } // don't need an "else" because the script is put in the AddAttributesToRender otherwise
            }
        }

        /// <summary>
        /// Registers the client script used for uplevel browsers
        /// </summary>
        protected virtual void RegisterClientScript()
        {
            var csType = GetType();

            if (!Page.ClientScript.IsClientScriptBlockRegistered(csType, ClientScriptUtility.LibraryScriptName))
            {
                Page.ClientScript.RegisterClientScriptBlock(csType, ClientScriptUtility.LibraryScriptName,
                                                            ClientScriptUtility.LibraryScript);
            }

            Page.ClientScript.RegisterArrayDeclaration(ClientScriptUtility.ArrayName, "'" + ClientID + "'");

            if (!Page.ClientScript.IsStartupScriptRegistered(csType, ClientScriptUtility.StartupScriptName))
            {
                Page.ClientScript.RegisterStartupScript(csType, ClientScriptUtility.StartupScriptName,
                                                        ClientScriptUtility.StartupScript);
            }
        }
    }
}